package com.atguigu.gulimall.order.service.impl;

import com.atguigu.common.vo.MemberRespVo;
import com.atguigu.gulimall.order.constant.OrderConstant;
import com.atguigu.gulimall.order.enume.OrderStatusEnum;
import com.atguigu.gulimall.order.feign.CartFeignService;
import com.atguigu.gulimall.order.feign.MemberFeignService;
import com.atguigu.gulimall.order.interceptor.LoginUserInterceptor;
import com.atguigu.gulimall.order.to.OrderCreateTo;
import com.atguigu.gulimall.order.vo.*;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.order.dao.OrderDao;
import com.atguigu.gulimall.order.entity.OrderEntity;
import com.atguigu.gulimall.order.service.OrderService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    @Autowired
    StringRedisTemplate redisTemplate;

//    @Autowired
//    MemberFeignService memberFeignService;

//    @Autowired
//    CartFeignService cartFeignService;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),
                new QueryWrapper<OrderEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 本地事务，在分布式系统只能控制自己的回滚，控制不了其他服务的回滚
     * @param vo
     * @return
     */
    @Transactional
    @Override
    public SubmitOrderResponseVo submitOrder(OrderSubmitVo vo) {
        SubmitOrderResponseVo response = new SubmitOrderResponseVo();
        // 从拦截器中获取用户ID
        MemberRespVo respVo = LoginUserInterceptor.loginUser.get();

        // 验证令牌【令牌对比和删除必须保证原子性】
        // 0令牌失败，1删除成功
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] " +
                "then return redis.call('del', KEYS[1]) " +
                "else return 0 end";
        String orderToken = vo.getOrderToken();

        // 原子验证令牌和删除令牌
        Long result = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),
                Arrays.asList(OrderConstant.USER_ORDER_TOKEN_PREFIX + respVo.getId()), orderToken);

        if (result == 0L) {
            // 令牌验证失败
            return response;
        } else {
            // 令牌验证成功
            // 下单：去创建订单，验令牌，验价格，锁库存
            OrderCreateTo order = createOrder();
            // TODO 订单创建成功发送消息给mq
            rabbitTemplate.convertAndSend("order-event-exchange", "order.create.order", order.getOrder());
        }
//        String redisToken = redisTemplate.opsForValue().get(OrderConstant.USER_ORDER_TOKEN_PREFIX + respVo.getId());
//        if (orderToken.equals(redisToken) && orderToken!=null) {
//            // 令牌验证通过
//            redisTemplate.delete(OrderConstant.USER_ORDER_TOKEN_PREFIX + respVo.getId());
//
//        } else {
//            // 不通过
//        }
        return response;
    }

    private OrderCreateTo createOrder() {
        OrderCreateTo orderCreateTo = new OrderCreateTo();

        // 1.生成订单号
        String orderSn = IdWorker.getTimeId();
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setOrderSn(orderSn);
        // 获取收货地址信息

        return orderCreateTo;
    }

    @Override
    public OrderConfirmVo confirmOrder() {
        OrderConfirmVo confirmVo = new OrderConfirmVo();
        MemberRespVo memberRespVo = LoginUserInterceptor.loginUser.get();
        // 获取之前的请求
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        CompletableFuture<Void> getAddressFuture = CompletableFuture.runAsync(() -> {
            // 1.远程查询所有的收货地址列表
            System.out.println("member线程：" + Thread.currentThread().getId());
            // 2.每一个线程都来共享之前的请求数据
            RequestContextHolder.setRequestAttributes(requestAttributes);
//            List<MemberAddressVo> address = memberFeignService.getAddress(memberRespVo.getId());
//            confirmVo.setAddress(address);
        });

        CompletableFuture<Void> cartFuture = CompletableFuture.runAsync(() -> {
            // 1.远程查询购物车所有选中的购物项
            System.out.println("cart线程："+Thread.currentThread().getId());
            // 每一个线程都来共享之前的请求数据
            RequestContextHolder.setRequestAttributes(requestAttributes);
//            List<OrderItemVo> items = cartFeignService.getCurrentUserCartItems();
//            confirmVo.setItems(items);
            // feign在远程调用之前要构造请求，调用很多的拦截器
        });//.thenAcceptAsync(()->{
//            List<OrderItemVo> items = confirmVo.getItems();
//            List<Long> collect = items.stream().map(item -> item.getSkuId()).collect(Collectors.toList());
//            return null;
//        });

        // 防重令牌
        String token = UUID.randomUUID().toString().replace("-", "");
        redisTemplate.opsForValue().set(OrderConstant.USER_ORDER_TOKEN_PREFIX+memberRespVo.getId(), token, 30, TimeUnit.MINUTES);
        confirmVo.setOrderToken(token);
        try {
            CompletableFuture.allOf(getAddressFuture, cartFuture).get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void closeOrder(OrderEntity entity) {
        // 查询当前这个订单的最新状态
        OrderEntity orderEntity = this.getById(entity.getId());
        int status = orderEntity.getStatus();
        int code = OrderStatusEnum.CREATE_NEW.getCode();
        if (status == code) {
            // 关单,修改订单状态
            OrderEntity update = new OrderEntity();
            update.setId(entity.getId());
            update.setStatus(OrderStatusEnum.CANCLED.getCode());
            this.updateById(update);
            // 发给mq
            rabbitTemplate.convertAndSend("order-event-exchange", "order.release.other", orderEntity);
        }
    }

}